import * as cc from "cc";
import { EventType } from "../GameSpecial/GameEventType";
import { GlobalEnum } from "../GameSpecial/GlobalEnum";
import Action3dManager, { ActionMngType } from "./Action3dManager";
import { CommonEnum } from "./CommonEnum";
import EventManager from "./EventManager";
import GlobalData from "./GlobalData";
import yyComponent from "./yyComponent";

const { ccclass, property } = cc._decorator;
/**banner误触按钮 */
@ccclass
export default class BannerToucherButton extends yyComponent {

    @property({
        type: cc.Enum(CommonEnum.BannerTouchType),
        tooltip: "按钮误触类型：\n" +
            "- bannerToucher_recommendPage：导流页使用的误触方式，按钮位置不会移动；\n\n" +
            "- bannerToucher_resultUI：结算页使用的误触方式，banner显示后，会根据后台配置选择延迟隐藏banner或移动按钮位置；\n\n" +
            "- noneBannerButton：没有误触，不处理banner的显示/隐藏的按钮，适用于OPPO平台等不使用误触banner的情况；\n\n"
    })
    public type: CommonEnum.BannerTouchType = CommonEnum.BannerTouchType.base;

    @property({ tooltip: "开关关闭时，按钮显示在正常位置的坐标" })
    protected normalPos: cc.Vec2 = cc.v2();
    @property({ tooltip: "开关打开时，按钮显示在banner位置的坐标" })
    protected touchPos: cc.Vec2 = cc.v2();

    @property({
        type: cc.Node,
        tooltip: "误触功能要控制的其他按钮，比如结算页要控制的观看视频的按钮",
    })
    protected otherBtn: cc.Node = null;
    @property({ tooltip: "开关关闭时，按钮显示在正常位置的坐标" })
    protected otherBtnNormalPos: cc.Vec2 = cc.v2();
    @property({ tooltip: "开关打开时，按钮显示在banner位置的坐标" })
    protected otherBtnTouchPos: cc.Vec2 = cc.v2();

    protected handler: { cb: Function, target?: any, data?: any };
    protected banner: { id: string, style?: any };

    public init(handler?: { cb: Function, target?: any, data?: any }, banner?: any) {
        this.handler = handler;
        this.banner = banner;
    }

    public reset() {
        this.resetBannerToucher();
    }

    public show(config?) {
        this.resetBannerToucher();
        this.showBannerToucher(config);
    }

    //#region banenr误触功能管理器
    protected bannerToucher: BannerToucher;
    protected resetBannerToucher() {
        if (!!this.bannerToucher) this.bannerToucher.reset();
    }
    protected showBannerToucher(config?) {
        if (!this.bannerToucher) {
            this.createBannerToucher(config);
        }
        this.bannerToucher.show(config);
    }
    protected createBannerToucher(config) {
        this.bannerToucher = BannerToucherManager.getBannerToucher(this.type, {
            config: config,
            banner: this.banner,
            handler: this.handler,
            data: {
                btn: this.node,
                normalPos: this.normalPos,
                touchPos: this.touchPos,
                otherBtn: this.otherBtn,
                otherBtnNormalPos: this.otherBtnNormalPos,
                otherBtnTouchPos: this.otherBtnTouchPos,
            },
        });
    }
    protected clickBanerToucher(handler?) {
        if (!!this.bannerToucher) this.bannerToucher.onClick(handler);
    }
    //#endregion

    protected onClick() {
        EventManager.emit(EventType.Common.SDKEvent.checkVisibleBanner, this.onHaveBanner.bind(this), this.onNoBanner.bind(this));
    }
    protected onHaveBanner() {
        this.clickBanerToucher();
    }
    protected onNoBanner() {
        this.runHandler();
    }
    /**执行按钮正常的点击回调 */
    protected runHandler() {
        EventManager.emit(EventType.Common.RecommendEvent.hideSingleRecommend);
        if (!this.handler) return;
        if (!!this.handler.target) {
            this.handler.cb.call(this.handler.target, this.handler.data);
        } else {
            this.handler.cb(this.handler.data);
        }
    }
}

/**banner误触功能管理器 */
class BannerToucherManager {

    /**
     * 获取一个管理banner误触功能的实例
     * @param type banenr误触类型
     * @param config banner误触配置
     */
    public static getBannerToucher(type, config?: toucherConfig): BannerToucher {
        let toucher = this.createBannerToucher(type);
        if (!toucher) {
            return null;
        }
        toucher.setConfig(config);
        return toucher;
    }
    protected static createBannerToucher(type) {
        switch (type) {
            case GlobalEnum.Common.BannerTouchType.bannerToucher_recommendPage: {
                return new BannerToucher_RecommendPage();
            }
            case GlobalEnum.Common.BannerTouchType.bannerToucher_resultUI: {
                return new BannerToucher_ResultUI();
            }
            case GlobalEnum.Common.BannerTouchType.noneBannerButton: {
                return new NoneBannerButton();
            }
        }
        return new NoneBannerButton();
    }

}

type toucherConfig = {
    /**误触配置 */
    config: any,
    /**要显示的banner参数 */
    banner: { id: string, style?: { horizontal?: string } },
    /**误触结束后的回调 */
    handler: Handler,
    /**其他要传递的参数 */
    data?: any,
}

type Handler = {
    cb: Function,
    target?: any,
    data?: any,
}

/**banner误触功能 */
class BannerToucher {

    public get type(): number { return GlobalEnum.Common.BannerTouchType.base; }

    public constructor(config?: toucherConfig) {
        this.init(config);
    }
    public init(data?: toucherConfig) {
        if (undefined !== data) {
            this.setData(data);
        }
    }
    protected setData(data: toucherConfig) {
        this.setBaseData(data);
        this.setOtherConfig(data);
    }
    /**设置基础通用数据及配置 */
    protected setBaseData(data: toucherConfig) {
        this.setVisible(data.config);
        this.banner = data.banner;
        this.setHandler(data.handler);
    }
    /**设置子类专属数据及配置 */
    protected setOtherConfig(data: toucherConfig) { }
    public reset() { }
    /**设置误触功能的全部配置，包括banner参数，回调函数，以及其他配置 */
    public setConfig(data: toucherConfig) { this.setData(data); }
    /**设置误触功能的具体参数 */
    public setTouchConfig(config: any) { }
    /**对应的按钮显示时调用 */
    public show(config?: toucherConfig) {
        this.reset();
        if (!!config) {
            this.setTouchConfig(config);
        }
    }
    /**对应的按钮隐藏时调用 */
    public hide() { }

    /******************************************************基础配置******************************************************/
    /**
     * 误触模式：
     * 1-正常模式，直接显示banner，相当于开关关闭
     * 2-导流模式，直接显示广告位代替banner
     * 3-banner模式，即打开误触
     */
    protected mode: number = 1;
    /**误触功能是否启用 */
    protected visible: boolean = false;
    protected setVisible(config) {
        if (!config) {
            this.visible = false;
            return;
        }
        this.visible = !!config[GlobalEnum.Common.RecommendFlowConfig.visible];
        let mode = config[GlobalEnum.Common.RecommendFlowConfig.mode];
        if (typeof mode === "number") {
            mode = mode.toString();
        }
        if (mode == "0" || mode == "z") {
            mode = "23567";
        }
        let index = Math.floor(Math.random() * (mode.length - 0.00001));
        this.mode = parseInt(mode[index]);
    }

    /******************************************************banner/广告位显隐******************************************************/
    /**要显示的banner配置，包括banner的ID，位置等 */
    protected banner: { id: string, style?: { horizontal?: string } };
    protected showBanner() {
        switch (this.mode) {
            case GlobalEnum.Common.BannerTouchMode.banner: {
                this._showBanner();
                break;
            }
            case GlobalEnum.Common.BannerTouchMode.recommend: {
                this._showRecommend();
                break;
            }
            default: {
                this._showBanner();
                break;
            }
        }
    }
    /**显示banner */
    protected _showBanner() {
        EventManager.emit(EventType.Common.SDKEvent.showBanner, this.banner);
    }
    /**显示广告位代替banner */
    protected _showRecommend() {
        console.log("BannerToucher.showRecommend.hideBanner");
        EventManager.emit(EventType.Common.SDKEvent.hideBanner);
        let cvs = GlobalData.get(GlobalEnum.Common.GlobalDataType.canvasTransform);
        //横屏游戏处理
        if (cvs.width > cvs.height) {
            let wdg: any = {};
            if (!!this.banner && !!this.banner.style) {
                switch (this.banner.style.horizontal) {
                    case "left": {
                        wdg.left = 20;
                        break;
                    }
                    case "middle": {
                        wdg.horizontalCenter = true;
                        break;
                    }
                    case "right": {
                        wdg.right = 20;
                        break;
                    }
                    default: {
                        wdg.horizontalCenter = true;
                        break;
                    }
                }
            }
            wdg.width = 600;
            wdg.bottom = 40;
            wdg.height = 170;
            EventManager.emit(EventType.Common.RecommendEvent.showInsteadBannerRecommend, {
                "name": "RecommendBanner_H",
                "AdID": "friend",
                "itemType": "icon",
                "widget": wdg,
            });
        } else {
            EventManager.emit(EventType.Common.RecommendEvent.showInsteadBannerRecommend, {
                "name": "RecommendBanner_H",
                "AdID": "friend",
                "itemType": "icon",
                "widget": {
                    "left": 0,
                    "right": 0,
                    "bottom": 40,
                    "height": 170
                }
            });
        }
    }
    protected hideBanner() {
        console.log("BannerToucher:hideBanner");
        EventManager.emit(EventType.Common.SDKEvent.hideBanner);
    }

    /******************************************************点击回调******************************************************/
    /**按钮正常的点击回调 */
    protected handler: Handler;
    protected setHandler(handler: Handler) {
        this.handler = handler;
    }
    /**执行按钮正常的点击回调 */
    protected runHandler() {
        EventManager.emit(EventType.Common.RecommendEvent.hideSingleRecommend);
        if (!this.handler) return;
        if (!!this.handler.target) {
            this.handler.cb.call(this.handler.target, this.handler.data);
        } else {
            this.handler.cb(this.handler.data);
        }
    }
    /**
     * 点击按钮
     * @returns 按钮的正常回调是否执行
     */
    public onClick(handler?: Handler): boolean {
        if (!!handler) {
            this.setHandler(handler);
        }
        if (!this.visible) {
            this.runHandler();
            return true;
        } else {
            return this.checkClick();
        }
    }
    /**检测点击效果 */
    protected checkClick(): boolean {
        return false;
    }

}

/**
 * 导流页闪屏误触：
 * 按钮点击N次后，延迟X秒出现banner，延迟Y秒隐藏banner，再次点击按钮生效；
 */
class BannerToucher_RecommendPage extends BannerToucher {
    public get type() { return GlobalEnum.Common.BannerTouchType.bannerToucher_recommendPage; }
    /**按钮已点击次数 */
    protected clickCount: number = 0;
    /**启动计时器延迟出现banner之前需要的按钮点击次数 */
    protected preClickCount: number = 0;
    /**预点击最小次数 */
    protected minClickCount: number = 0;
    /**预点击最大次数 */
    protected maxClickCount: number = 0;
    /**banner出现的延迟时间，单位：秒 */
    protected showBannerDelay: number = 0;
    /**banner隐藏的延迟时间，单位：秒 */
    protected hideBannerDelay: number = 0;

    public reset() {
        this.clickCount = 0;
        this.randomPreclickCount();
    }
    protected randomPreclickCount() {
        this.preClickCount = this.minClickCount + Math.round((this.maxClickCount - this.minClickCount) * Math.random());
    }

    protected setOtherConfig(data: toucherConfig) {
        this.setTouchConfig(data.config);
    }

    public setTouchConfig(config) {
        if (!config) {
            this.visible = false;
            return;
        }
        //按钮预点击次数
        let count = config[GlobalEnum.Common.RecommendFlowConfig.preClickCount];
        if (typeof count === "number") {
            this.minClickCount = count;
            this.maxClickCount = count;
        } else if (typeof count === "string") {
            if (count.indexOf("-") >= 0) {
                let arr = count.split("-");
                this.minClickCount = parseInt(arr[0]);
                this.maxClickCount = parseInt(arr[1]);
            } else {
                this.minClickCount = parseInt(count);
                this.maxClickCount = parseInt(count);
            }
        }
        this.randomPreclickCount();

        //banner延迟显示/隐藏
        let delay = config[GlobalEnum.Common.RecommendFlowConfig.recommendBannerShowDelay];
        if (typeof delay === "string") {
            delay = parseFloat(delay);
        }
        this.showBannerDelay = delay;
        if (this.showBannerDelay == 0) {
            this.visible = false;
        }
        delay = config[GlobalEnum.Common.RecommendFlowConfig.recommendBannerHideDelay];
        if (typeof delay === "string") {
            delay = parseFloat(delay);
        }
        this.hideBannerDelay = delay;
    }

    public show(config?) {
        this.reset();
        if (!!config) {
            this.setVisible(config);
            this.setTouchConfig(config);
        }
        if (this.mode == GlobalEnum.Common.BannerTouchMode.normal) {
            this.visible = false;
        }

    }

    /**检测点击效果 */
    protected checkClick() {
        this.preClickCount -= 1;
        if (this.preClickCount > 0) return false;

        if (this.showBannerDelay == 0 && this.hideBannerDelay == 0) {
            this.runHandler();
            return true;
        }

        switch (this.clickCount) {
            case 0: {
                this.clickCount = 1;
                //延迟1秒显示banner
                setTimeout(() => {
                    console.log("延迟显示banner");
                    EventManager.once(EventType.Common.SDKEvent.showBannerSuccess, this.delayHideBanner0, this);
                    this.showBanner();
                }, this.showBannerDelay * 1000);
                return false;
            }
            case 1: {
                return false;
            }
            case 2: {
                this.runHandler();
                return true;
            }
        }
        return false;
    }
    protected delayHideBanner0() {
        setTimeout(() => {
            console.log("延迟隐藏banner");
            this.hideBanner();
            this.clickCount = 2;
        }, this.hideBannerDelay * 1000);
    }
}

/**
 * 结算页闪屏方式：
 * 按钮点击N次后，延迟X秒出现banner，延迟Y秒隐藏banner，再次点击按钮生效；
 * 开关关闭时，直接显示banner，设置按钮位置在banner之外
 */
class BannerToucher_ResultUI extends BannerToucher_RecommendPage {
    public get type() { return GlobalEnum.Common.BannerTouchType.bannerToucher_resultUI; }

    /**误触对应的按钮 */
    protected btn: cc.Node = null;
    /**误触关闭时按钮位置 */
    protected btnNormalPos: cc.Vec2;
    /**误触开启时按钮位置 */
    protected btnTouchPos: cc.Vec2;

    protected otherBtn: cc.Node = null;
    protected otherBtnNormalPos: cc.Vec2;
    protected otherBtnTouchPos: cc.Vec2;
    protected setBtnNormalPos() {
        let actMng = Action3dManager.getMng(ActionMngType.UI);
        if (!!this.btn) {
            actMng.stopAllActions(this.btn);
            this.btn.setPosition(this.btnNormalPos.x, this.btnNormalPos.y, 0);
        }
        if (!!this.otherBtn) {
            actMng.stopAllActions(this.otherBtn);
            this.otherBtn.setPosition(this.otherBtnNormalPos.x, this.otherBtnNormalPos.y, 0);
        }
    }
    protected setBtnTouchPos() {
        let actMng = Action3dManager.getMng(ActionMngType.UI);
        if (!!this.btn) {
            actMng.stopAllActions(this.btn);
            this.btn.setPosition(this.btnTouchPos.x, this.btnTouchPos.y, 0);
        }
        if (!!this.otherBtn) {
            actMng.stopAllActions(this.otherBtn);
            this.otherBtn.setPosition(this.otherBtnTouchPos.x, this.otherBtnTouchPos.y, 0);
        }
    }
    //移动按钮到正常位置
    protected moveBtn() {
        if (!this.btn) return;
        let move = Action3dManager.moveTo(1, this.btnNormalPos.x, this.btnNormalPos.y, 0);
        Action3dManager.getMng(ActionMngType.UI).runAction(this.btn, move);
    }
    protected moveOtherBtn() {
        if (!this.otherBtn) return;
        let move = Action3dManager.moveTo(1, this.otherBtnNormalPos.x, this.otherBtnNormalPos.y, 0);
        Action3dManager.getMng(ActionMngType.UI).runAction(this.otherBtn, move);
    }

    protected showBannerDelay2: number = 0;
    /**子类专属参数 */
    protected setOtherConfig(data: toucherConfig) {
        this.setTouchConfig(data.config);

        if (!!data.data) {
            this.btn = data.data.btn;
            this.btnNormalPos = data.data.normalPos;
            this.btnTouchPos = data.data.touchPos;
            this.otherBtn = data.data.otherBtn;
            this.otherBtnNormalPos = data.data.otherBtnNormalPos;
            this.otherBtnTouchPos = data.data.otherBtnTouchPos;
        }
    }
    /**误触参数 */
    public setTouchConfig(config) {
        if (!config) {
            this.visible = false;
            return;
        }
        //按钮预点击次数
        let count = config[GlobalEnum.Common.RecommendFlowConfig.preClickCount];
        if (typeof count === "number") {
            this.minClickCount = count;
            this.maxClickCount = count;
        } else if (typeof count === "string") {
            if (count.indexOf("-") >= 0) {
                let arr = count.split("-");
                this.minClickCount = parseInt(arr[0]);
                this.maxClickCount = parseInt(arr[1]);
            } else {
                this.minClickCount = parseInt(count);
                this.maxClickCount = parseInt(count);
            }
        }
        this.randomPreclickCount();

        //banner延迟显示/隐藏
        let delay = config[GlobalEnum.Common.RecommendFlowConfig.shanPinShowBannerDelay];
        if (typeof delay === "string") {
            delay = parseFloat(delay);
        }
        this.showBannerDelay = delay;
        if (this.showBannerDelay == 0) {
            this.visible = false;
        }
        delay = config[GlobalEnum.Common.RecommendFlowConfig.shanPinHideBannerDelay];
        if (typeof delay === "string") {
            delay = parseFloat(delay);
        }
        this.hideBannerDelay = delay;

        delay = config[GlobalEnum.Common.RecommendFlowConfig.shanPinShowBannerDelay2];
        if (typeof delay === "string") {
            delay = parseFloat(delay);
        }
        if (!delay) {
            delay = 0.6;
        }
        this.showBannerDelay2 = delay;
    }

    public show(config?) {
        this.reset();
        if (!!config) {
            this.setVisible(config);
            this.setTouchConfig(config);
        }
        if (this.mode == GlobalEnum.Common.BannerTouchMode.normal) {
            this.visible = false;
        }
        if (!!this.visible) {
            switch (this.mode) {
                case GlobalEnum.Common.BannerTouchMode.showSingleRecommend: {
                    this.setBtnNormalPos();
                    EventManager.emit(EventType.Common.RecommendEvent.showSingleRecommend, "resultSingleBanner");
                    this.visible = false;
                    break;
                }
                case GlobalEnum.Common.BannerTouchMode.moveButtonFast: {
                    this.clickCount = 1;
                    this.setBtnTouchPos();
                    setTimeout(() => {
                        this._showBanner();
                    }, this.showBannerDelay * 1000);
                    setTimeout(() => {
                        this.setBtnNormalPos();
                        this.visible = false;
                        this.clickCount = 2;
                    }, this.hideBannerDelay * 1000);
                    break;
                }
                default: {
                    this.setBtnTouchPos();
                    if (this.preClickCount <= 0) {
                        this.step1();
                    }
                    break;
                }
            }
        } else {
            this.setBtnNormalPos();
            setTimeout(() => {
                console.log("直接显示banner");
                this._showBanner();
            }, 500);
        }
    }
    /**误触触发后的第一步操作：延迟显示banner */
    protected step1() {
        if (this.mode == GlobalEnum.Common.BannerTouchMode.moveButtonFast) {
            return;
        }
        this.clickCount = 1;
        setTimeout(() => {
            EventManager.once(EventType.Common.SDKEvent.showBannerSuccess, this.step2, this);
            this.showBanner();
        }, this.showBannerDelay * 1000);
    }
    /**banner显示后的第二步操作，根据后台配置的模式选择隐藏banner或移动按钮 */
    protected step2() {
        switch (this.mode) {
            //延迟隐藏banner
            case GlobalEnum.Common.BannerTouchMode.banner: {
                setTimeout(() => {
                    this.hideBanner();
                    this.clickCount = 2;
                }, this.hideBannerDelay * 1000);
                break;
            }
            //延迟移动按钮
            case GlobalEnum.Common.BannerTouchMode.moveButton: {
                setTimeout(() => {
                    this.moveBtn();
                    this.moveOtherBtn();
                    this.clickCount = 2;
                }, 500);
                break;
            }
            //延迟隐藏banner后延迟再次显示banner
            case GlobalEnum.Common.BannerTouchMode.showBannerTwice: {
                setTimeout(() => {
                    this.hideBanner();
                    this.clickCount = 1;
                    this.step3();
                }, this.hideBannerDelay * 1000);
                break;
            }
            default: {
                this.clickCount = 2;
                break;
            }
        }
    }
    protected step3() {
        switch (this.mode) {
            case GlobalEnum.Common.BannerTouchMode.showBannerTwice: {
                setTimeout(() => {
                    this.clickCount = 1;
                    EventManager.once(EventType.Common.SDKEvent.showBannerSuccess, this.step4, this);
                    this.showBanner();
                }, this.showBannerDelay2 * 1000);
                break;
            }
            default: {
                this.clickCount = 2;
                break;
            }
        }
    }
    protected step4() {
        switch (this.mode) {
            case GlobalEnum.Common.BannerTouchMode.showBannerTwice: {
                setTimeout(() => {
                    this.hideBanner();
                    this.clickCount = 2;
                }, this.hideBannerDelay * 1000);
                break;
            }
            default: {
                this.clickCount = 2;
                break;
            }
        }
    }

    /**检测点击效果 */
    protected checkClick() {
        this.preClickCount -= 1;
        if (this.preClickCount > 0) return false;

        if (this.showBannerDelay == 0 && this.hideBannerDelay == 0) {
            this.runHandler();
            return true;
        }

        switch (this.clickCount) {
            case 0: {
                this.step1();
                return false;
            }
            case 1: {
                return false;
            }
            case 2: {
                this.runHandler();
                return true;
            }
        }
        return false;
    }

}

/**
 * 单纯的按钮，不显示广告，没有误触
 */
class NoneBannerButton extends BannerToucher {
    public get type() { return GlobalEnum.Common.BannerTouchType.noneBannerButton; }
    public show() { }
    /**
     * 点击按钮
     * @returns 按钮的正常回调是否执行
     */
    public onClick(handler?: Handler): boolean {
        if (!!handler) {
            this.setHandler(handler);
        }
        this.runHandler();
        return true;
    }
}
